Crate custom_derive [] [src]

Note: This crate has been superseded by macro-attr.

This crate provides a macro that enables the use of custom derive attributes.

To use it, make sure you link to the crate like so:

#[macro_use] extern crate custom_derive;

Note: the custom_derive! macro itself is not documented, as the automatic documentation for it would be uselessly huge and incomprehensible.

Usage

The macro should be used to wrap an entire single enum or struct declaration, including its attributes (both derive and others). All derivation attributes which the macro does not recognise will be assumed to be custom, and treated accordingly.

custom_derive! assumes that custom derivations are implemented as macros (of the same name). For example, here is a simple derivation macro:

#[macro_use] extern crate custom_derive;

trait TypeName {
    fn type_name() -> &'static str;
}

trait ReprType {
    type Repr;
}

macro_rules! TypeName {
    (() $(pub)* enum $name:ident $($tail:tt)*) => { TypeName! { @impl $name } };
    (() $(pub)* struct $name:ident $($tail:tt)*) => { TypeName! { @impl $name } };

    (@impl $name:ident) => {
        impl TypeName for $name {
            fn type_name() -> &'static str { stringify!($name) }
        }
    };
}

macro_rules! TryFrom {
    (($repr:ty) $(pub)* enum $name:ident $($tail:tt)*) => {
        impl ReprType for $name {
            type Repr = $repr;
        }
    };
}

custom_derive! {
    #[allow(dead_code)]
    #[repr(u8)]
    #[derive(Clone, Copy, Debug, TryFrom(u8), TypeName)]
    enum Foo { A, B }
}

fn main() {
    let foo = Foo::B;
    let v = foo as <Foo as ReprType>::Repr;
    let msg = format!("{}: {:?} ({:?})", Foo::type_name(), foo, v);
    assert_eq!(msg, "Foo: B (1)");
}

First, note that custom_derive! passes any arguments on the derivation attribute to the macro. In the case of attributes without any arguments, () is passed instead.

Secondly, the macro is passed the entire item, sans attributes. It is the derivation macro's job to parse the item correctly.

Third, each derivation macro is expected to result in zero or more items, not including the item itself. As a result, it is not possible to mutate the item in any way, or attach additional attributes to it.

Finally, @impl is merely a trick to pack multiple, different functions into a single macro. The sequence has no special meaning; it is simply distinct from the usual invocation syntax.